package cn.com.bluemoon.daps.common.datascope.config;

import cn.com.bluemoon.daps.api.sys.RemoteSysOperateLogService;
import cn.com.bluemoon.daps.common.datascope.BmPermission;
import cn.com.bluemoon.daps.common.datascope.IgnorePermission;
import cn.com.bluemoon.daps.common.datascope.interceptor.WebNetworkRequestInterceptor;
import cn.com.bluemoon.daps.common.datascope.interceptor.WebOperateLogCollectInterceptor;
import cn.com.bluemoon.daps.common.datascope.interceptor.WebPermissionRequestInterceptor;
import cn.com.bluemoon.daps.common.domain.UserInfoHolder;
import cn.com.bluemoon.daps.domp.api.IDompService;
import cn.com.bluemoon.daps.domp.api.LocalDompService;
import cn.com.bluemoon.daps.domp.api.LocalUserService;
import cn.com.bluemoon.daps.domp.api.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * 注：
 * <p>1.{@see ControllerAop}的@Order(Integer.MAX_VALUE - 2) 确保比{UserPermissionSingleRowAop}的order后，保证认证通过了才进行接口调用
 * <p>2.确保{UserPermissionSingleRowAop}的order 在拦截器{@link AuthWebConfig#addInterceptors(InterceptorRegistry)}的后
 * 保证{@link UserInfoHolder#getUserInfo()}已存在数据
 * <p>3.确保拦截器{@link AuthWebConfig#addInterceptors(InterceptorRegistry)}最先执行，权限认证
 *
 * @author Jarod.Kong
 */
@Configuration
@Slf4j
@ConditionalOnProperty(
        value = {"bm.dap.http.auth.enable"},
        matchIfMissing = true
)
public class AuthWebConfig implements WebMvcConfigurer {

    private static final List<String> interceptorExcludePathPatterns = new ArrayList<String>() {{
        add("/error");
        add("/swagger-resources/**");
        add("/v2/**");
        add("/swagger-ui.html");
        add("/swagger-resources/**");
        add("/webjars/springfox-swagger-ui/**");
        add("/csrf");
    }};

    @Resource
    @Lazy
    private LocalDompService dompService;

    @Resource
    @Lazy
    private LocalUserService userService;

    @Resource
    private BmVPNProperties bmVPNProperties;

    @Resource
    @Lazy
    private RemoteSysOperateLogService remoteSysOperateLogService;

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedHeaders("*")
                .allowedMethods("POST", "GET", "PUT", "DELETE")
                .allowedOrigins("*")
                .exposedHeaders("Set-Cookie")
//                .allowCredentials(true)
                .maxAge(3600);
    }

    /**
     * <p>
     * {@link IgnorePermission} 直接忽略权限，完全开放
     * {@link BmPermission} 考虑token有效的情况下
     * {@link BmPermission#ignore()}为true代表<em>在token有效情况下，进行放行，有别于{@link IgnorePermission}</em>
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 加入网络拦截器优先与权限认证
        registry.addInterceptor(new WebNetworkRequestInterceptor(bmVPNProperties))
                .addPathPatterns("/**")
                .order(Integer.MAX_VALUE - 2);
        // 加入权限认证
        registry.addInterceptor(new WebPermissionRequestInterceptor(userService, dompService))
                .addPathPatterns("/**")
                .excludePathPatterns(interceptorExcludePathPatterns).order(Integer.MAX_VALUE - 1);
        // 操作日志记录
        registry.addInterceptor(new WebOperateLogCollectInterceptor(dompService, remoteSysOperateLogService))
                .addPathPatterns("/**")
                .excludePathPatterns(interceptorExcludePathPatterns).order(Integer.MAX_VALUE-4);

    }

    /**
     * 跳过拦截的路径
     */
    public void addExcludePathPattern(String path) {
        interceptorExcludePathPatterns.add(path);
    }


}
